package modbus

import (
	"encoding/binary"
	"fmt"
)

// HighPerformanceClient 高性能客户端接口
// 提供可选的高性能API，减少内存分配和GC压力
type HighPerformanceClient interface {
	Client // 继承所有标准客户端接口

	// ReadCoilsWithBuf 使用提供的缓冲区读取线圈，减少内存分配
	ReadCoilsWithBuf(slaveID byte, address, quantity uint16, buf []byte) (int, error)

	// ReadHoldingRegistersWithBuf 使用提供的缓冲区读取保持寄存器
	ReadHoldingRegistersWithBuf(slaveID byte, address, quantity uint16, buf []uint16) (int, error)

	// WriteMultipleRegistersOptimized 优化的批量写寄存器（零拷贝）
	WriteMultipleRegistersOptimized(slaveID byte, address uint16, values []uint16) error
}

// highPerformanceClient 高性能客户端实现
type highPerformanceClient struct {
	*client
}

// NewHighPerformanceClient 创建高性能客户端
// 完全向后兼容，可以直接替换标准客户端使用
func NewHighPerformanceClient(p ClientProvider, opts ...Option) HighPerformanceClient {
	c := NewClient(p, opts...).(*client)
	return &highPerformanceClient{client: c}
}

// ReadCoilsWithBuf 使用提供的缓冲区读取线圈，减少内存分配
// buf: 用户提供的缓冲区，建议容量至少为 (quantity+7)/8 字节
// 返回: 实际读取的字节数和错误
func (sf *highPerformanceClient) ReadCoilsWithBuf(slaveID byte, address, quantity uint16, buf []byte) (int, error) {
	// 复用标准实现进行验证和网络通信
	data, err := sf.client.ReadCoils(slaveID, address, quantity)
	if err != nil {
		return 0, err
	}

	// 将结果复制到用户提供的缓冲区
	n := copy(buf, data)
	return n, nil
}

// ReadHoldingRegistersWithBuf 使用提供的缓冲区读取保持寄存器
// buf: 用户提供的缓冲区，建议容量至少为 quantity 个uint16
// 返回: 实际读取的寄存器数量和错误
func (sf *highPerformanceClient) ReadHoldingRegistersWithBuf(slaveID byte, address, quantity uint16, buf []uint16) (int, error) {
	// 获取原始字节数据
	data, err := sf.client.ReadHoldingRegistersBytes(slaveID, address, quantity)
	if err != nil {
		return 0, err
	}

	// 直接在用户缓冲区中解析，避免中间分配
	count := len(data) / 2
	if len(buf) < count {
		count = len(buf)
	}

	for i := 0; i < count; i++ {
		buf[i] = binary.BigEndian.Uint16(data[i*2:])
	}

	return count, nil
}

// WriteMultipleRegistersOptimized 优化的批量写寄存器（零拷贝）
// 直接使用uint16切片，避免类型转换分配
func (sf *highPerformanceClient) WriteMultipleRegistersOptimized(slaveID byte, address uint16, values []uint16) error {
	if slaveID > sf.addressMax {
		return SlaveIDRangeError(slaveID, AddressBroadCast, sf.addressMax)
	}

	quantity := uint16(len(values))
	if quantity < WriteRegQuantityMin || quantity > WriteRegQuantityMax {
		return QuantityRangeError(quantity, WriteRegQuantityMin, WriteRegQuantityMax)
	}

	// 使用池化的字节切片进行零拷贝转换
	data, cleanup := uint162BytesReuse(values...)
	defer cleanup()

	response, err := sf.Send(slaveID, ProtocolDataUnit{
		FuncCode: FuncCodeWriteMultipleRegisters,
		Data:     pduDataBlockSuffix(data, address, quantity),
	})

	switch {
	case err != nil:
		return err
	case len(response.Data) != 4:
		return ResponseSizeError(len(response.Data), 4)
	case binary.BigEndian.Uint16(response.Data) != address:
		return ResponseAddressError(binary.BigEndian.Uint16(response.Data), address)
	case binary.BigEndian.Uint16(response.Data[2:]) != quantity:
		return ResponseValueError(binary.BigEndian.Uint16(response.Data[2:]), quantity)
	}
	return nil
}

// BatchOperations 批量操作API，用于高吞吐量场景
type BatchOperations struct {
	client HighPerformanceClient
	buf    []byte   // 复用的字节缓冲区
	regBuf []uint16 // 复用的寄存器缓冲区
}

// NewBatchOperations 创建批量操作实例
func NewBatchOperations(client HighPerformanceClient) *BatchOperations {
	return &BatchOperations{
		client: client,
		buf:    make([]byte, 256),   // 预分配256字节缓冲区
		regBuf: make([]uint16, 128), // 预分配128个寄存器缓冲区
	}
}

// ReadMultipleCoils 批量读取多个线圈组
func (bo *BatchOperations) ReadMultipleCoils(slaveID byte, addresses []uint16, quantities []uint16) ([][]byte, error) {
	if len(addresses) != len(quantities) {
		return nil, fmt.Errorf("addresses and quantities length mismatch")
	}

	results := make([][]byte, len(addresses))

	for i, addr := range addresses {
		quantity := quantities[i]
		expectedBytes := int((quantity + 7) / 8)

		// 确保缓冲区足够大
		if len(bo.buf) < expectedBytes {
			bo.buf = make([]byte, expectedBytes*2)
		}

		n, err := bo.client.ReadCoilsWithBuf(slaveID, addr, quantity, bo.buf)
		if err != nil {
			return nil, err
		}

		// 复制结果到独立的切片
		results[i] = make([]byte, n)
		copy(results[i], bo.buf[:n])
	}

	return results, nil
}

// ReadMultipleHoldingRegisters 批量读取多个保持寄存器组
func (bo *BatchOperations) ReadMultipleHoldingRegisters(slaveID byte, addresses []uint16, quantities []uint16) ([][]uint16, error) {
	if len(addresses) != len(quantities) {
		return nil, fmt.Errorf("addresses and quantities length mismatch")
	}

	results := make([][]uint16, len(addresses))

	for i, addr := range addresses {
		quantity := quantities[i]

		// 确保缓冲区足够大
		if len(bo.regBuf) < int(quantity) {
			bo.regBuf = make([]uint16, quantity*2)
		}

		n, err := bo.client.ReadHoldingRegistersWithBuf(slaveID, addr, quantity, bo.regBuf)
		if err != nil {
			return nil, err
		}

		// 复制结果到独立的切片
		results[i] = make([]uint16, n)
		copy(results[i], bo.regBuf[:n])
	}

	return results, nil
}
